import sdk as draft
import logging
import os
import sys
import requests
import json
from functools import wraps
from datetime import datetime
from rest_framework import status
from rest_framework.response import Response
import lib.settings as settings
from typing import Dict, Any, Optional, Union

# 添加项目根目录到路径
project_root = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
sys.path.insert(0, project_root)
logger = logging.getLogger('api')

# 装饰器可以在函数前执行 比如 api_error_handler 函数，可以在函数执行之前，先执行装饰器中的代码
# func 就是一个 函数指针


def api_error_handler(func):
    """API错误处理装饰器"""
    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            logger.error(f"❌ {func.__name__} 失败: {e}")
            return Response({
                "success": False,
                "message": f"操作失败: {str(e)}"
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    return wrapper

# **kwargs 的意思是 可以传递任意数量的变量 类似Java剩余运算符 ...args


def create_success_response(message, **kwargs):
    """创建成功响应"""
    data = {"success": True, "message": message}

    # update函数可以更新字典内容 可以是列表 也可以是字典
    """
        dict1 = {"name": "Alice", "age": 30}
        items = [("age", 31), ("city", "New York")]

        dict1.update(items)
        print(dict1)  # 输出: {'name': 'Alice', 'age': 31, 'city': 'New York'}
        
    """
    data.update(kwargs)
    return Response(data)


def create_error_response(message, status_code=status.HTTP_400_BAD_REQUEST):
    """创建错误响应"""
    return Response({
        "success": False,
        "message": message
    }, status=status_code)


# TODO 创建的基础脚本对象 这个Script_file 对象初始化后就是剪映的基础模板，可以直接套用
def create_basic_script() -> draft.Script_file:
    return draft.Script_file(1920, 1080, fps=30)


# 这个函数可以将草稿内容保存到文件中
def save_draft_to_file(draft_content, filename=None):
    if filename is None:
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        filename = f"draft_{timestamp}.json"

    # 使用Django settings中的配置 /config/settings.py
    web_output_dir = getattr(settings, 'WEB_OUTPUT_DIR',
                             os.path.join(project_root, "web_outputs"))
    os.makedirs(web_output_dir, exist_ok=True)
    file_path = os.path.join(web_output_dir, filename)

    with open(file_path, 'w', encoding='utf-8') as f:
        json.dump(draft_content, f, ensure_ascii=False, indent=2)

    logger.info(f"✅ 草稿文件已保存: {file_path}")
    return file_path


def get_project_path():
    """获取项目保存路径"""
    # 使用与get_asset_path相同的基础目录，但子目录不同
    base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    project_dir = os.path.join(base_dir, 'projects')
    os.makedirs(project_dir, exist_ok=True)
    return project_dir


def get_output_path(project_name):
    """获取输出文件路径"""
    return os.path.join(get_project_path(), project_name)


def create_and_save_script(script, template_name, success_message, additional_data=None):
    """序列化草稿脚本对象并返回，不保存到本地

    Args:
        script: 草稿脚本对象
        template_name: 模板名称(仅用于标识，不会创建实际的文件)
        success_message: 成功消息
        additional_data: 附加数据

    Returns:
        Response: API响应，包含序列化的脚本内容
    """
    # 将Script_file对象序列化为JSON字符串，然后解析为字典
    script_json = json.loads(script.dumps())

    # 准备项目信息
    project_info = {
        "name": template_name
    }

    # 构建响应
    response_data = {
        "template_name": template_name,
        "project_info": project_info,
        "draft_content": script_json  # 直接返回序列化后的草稿内容
    }

    if additional_data:
        # 确保additional_data不覆盖draft_content
        if isinstance(additional_data, dict) and "draft_content" in additional_data:
            additional_data.pop("draft_content")
        response_data.update(additional_data)

    return create_success_response(success_message, **response_data)


class HttpRequestUtils:
    """HTTP请求工具类，封装requests库提供便捷的HTTP调用方法"""

    # 默认超时时间（秒）
    DEFAULT_TIMEOUT = 30

    # 默认请求头
    DEFAULT_HEADERS = {
        'User-Agent': 'JianYing-API/1.0',
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    }

    @staticmethod
    def _make_request(method: str, url: str,
                      data: Optional[Union[Dict, str, bytes]] = None,
                      params: Optional[Dict] = None,
                      headers: Optional[Dict] = None,
                      timeout: Optional[int] = None,
                      auth: Optional[tuple] = None,
                      cookies: Optional[Dict] = None,
                      allow_redirects: bool = True,
                      verify: bool = True,
                      stream: bool = False,
                      files: Optional[Dict] = None,
                      **kwargs) -> Dict[str, Any]:
        """
        内部统一请求方法

        Args:
            method: HTTP方法 (GET, POST, PUT, DELETE, etc.)
            url: 请求URL
            data: 请求体数据
            params: URL参数
            headers: 请求头
            timeout: 超时时间
            auth: 认证信息 (username, password)
            cookies: Cookie字典
            allow_redirects: 是否允许重定向
            verify: 是否验证SSL证书
            stream: 是否流式下载
            files: 文件上传字典
            **kwargs: 其他requests参数

        Returns:
            Dict: 包含响应信息的字典
        """
        try:
            # 设置默认值
            if timeout is None:
                timeout = HttpRequestUtils.DEFAULT_TIMEOUT

            if headers is None:
                headers = HttpRequestUtils.DEFAULT_HEADERS.copy()
            else:
                # 合并默认头和自定义头
                merged_headers = HttpRequestUtils.DEFAULT_HEADERS.copy()
                merged_headers.update(headers)
                headers = merged_headers

            # 如果有文件上传，移除Content-Type让requests自动设置
            if files:
                headers.pop('Content-Type', None)

            # 如果data是字典且不是文件上传，转换为JSON
            if isinstance(data, dict) and not files:
                data = json.dumps(data, ensure_ascii=False)

            logger.info(f"🌐 {method} {url}")
            if params:
                logger.debug(f"📝 参数: {params}")
            if data and not files:
                logger.debug(f"📤 数据: {data}")

            # 发送请求
            response = requests.request(
                method=method,
                url=url,
                data=data,
                params=params,
                headers=headers,
                timeout=timeout,
                auth=auth,
                cookies=cookies,
                allow_redirects=allow_redirects,
                verify=verify,
                stream=stream,
                files=files,
                **kwargs
            )

            # 记录响应状态
            logger.info(f"📨 响应状态: {response.status_code}")

            # 构建返回结果
            result = {
                'success': response.status_code < 400,
                'status_code': response.status_code,
                'headers': dict(response.headers),
                'url': response.url,
                'elapsed': response.elapsed.total_seconds()
            }

            # 尝试解析JSON响应
            try:
                result['json'] = response.json()
                result['data'] = result['json']  # 别名，方便使用
            except (ValueError, json.JSONDecodeError):
                result['text'] = response.text
                result['data'] = response.text

            # 如果是流式响应，保存响应对象
            if stream:
                result['response'] = response

            return result

        except requests.exceptions.Timeout:
            logger.error(f"⏰ 请求超时: {url}")
            return {
                'success': False,
                'error': 'timeout',
                'message': f'请求超时 ({timeout}秒)',
                'url': url
            }
        except requests.exceptions.ConnectionError:
            logger.error(f"🔌 连接错误: {url}")
            return {
                'success': False,
                'error': 'connection_error',
                'message': '网络连接错误',
                'url': url
            }
        except requests.exceptions.RequestException as e:
            logger.error(f"❌ 请求异常: {url} - {str(e)}")
            return {
                'success': False,
                'error': 'request_exception',
                'message': str(e),
                'url': url
            }
        except Exception as e:
            logger.error(f"💥 未知错误: {url} - {str(e)}")
            return {
                'success': False,
                'error': 'unknown_error',
                'message': str(e),
                'url': url
            }

    @staticmethod
    def get(url: str, params: Optional[Dict] = None, **kwargs) -> Dict[str, Any]:
        """
        发送GET请求

        Args:
            url: 请求URL
            params: URL参数
            **kwargs: 其他请求参数

        Returns:
            Dict: 响应结果
        """
        return HttpRequestUtils._make_request('GET', url, params=params, **kwargs)

    @staticmethod
    def post(url: str, data: Optional[Union[Dict, str, bytes]] = None,
             json_data: Optional[Dict] = None, **kwargs) -> Dict[str, Any]:
        """
        发送POST请求

        Args:
            url: 请求URL
            data: 请求体数据
            json_data: JSON数据（会自动设置Content-Type）
            **kwargs: 其他请求参数

        Returns:
            Dict: 响应结果
        """
        if json_data is not None:
            data = json_data
        return HttpRequestUtils._make_request('POST', url, data=data, **kwargs)

    @staticmethod
    def put(url: str, data: Optional[Union[Dict, str, bytes]] = None,
            json_data: Optional[Dict] = None, **kwargs) -> Dict[str, Any]:
        """
        发送PUT请求

        Args:
            url: 请求URL
            data: 请求体数据
            json_data: JSON数据
            **kwargs: 其他请求参数

        Returns:
            Dict: 响应结果
        """
        if json_data is not None:
            data = json_data
        return HttpRequestUtils._make_request('PUT', url, data=data, **kwargs)

    @staticmethod
    def patch(url: str, data: Optional[Union[Dict, str, bytes]] = None,
              json_data: Optional[Dict] = None, **kwargs) -> Dict[str, Any]:
        """
        发送PATCH请求

        Args:
            url: 请求URL
            data: 请求体数据
            json_data: JSON数据
            **kwargs: 其他请求参数

        Returns:
            Dict: 响应结果
        """
        if json_data is not None:
            data = json_data
        return HttpRequestUtils._make_request('PATCH', url, data=data, **kwargs)

    @staticmethod
    def delete(url: str, **kwargs) -> Dict[str, Any]:
        """
        发送DELETE请求

        Args:
            url: 请求URL
            **kwargs: 其他请求参数

        Returns:
            Dict: 响应结果
        """
        return HttpRequestUtils._make_request('DELETE', url, **kwargs)

    @staticmethod
    def head(url: str, **kwargs) -> Dict[str, Any]:
        """
        发送HEAD请求

        Args:
            url: 请求URL
            **kwargs: 其他请求参数

        Returns:
            Dict: 响应结果
        """
        return HttpRequestUtils._make_request('HEAD', url, **kwargs)

    @staticmethod
    def options(url: str, **kwargs) -> Dict[str, Any]:
        """
        发送OPTIONS请求

        Args:
            url: 请求URL
            **kwargs: 其他请求参数

        Returns:
            Dict: 响应结果
        """
        return HttpRequestUtils._make_request('OPTIONS', url, **kwargs)

    @staticmethod
    def upload_file(url: str, file_path: str, file_field: str = 'file',
                    data: Optional[Dict] = None, **kwargs) -> Dict[str, Any]:
        """
        上传文件

        Args:
            url: 上传URL
            file_path: 文件路径
            file_field: 文件字段名
            data: 额外的表单数据
            **kwargs: 其他请求参数

        Returns:
            Dict: 响应结果
        """
        if not os.path.exists(file_path):
            return {
                'success': False,
                'error': 'file_not_found',
                'message': f'文件不存在: {file_path}'
            }

        try:
            with open(file_path, 'rb') as f:
                files = {file_field: (os.path.basename(file_path), f)}
                return HttpRequestUtils._make_request('POST', url, data=data, files=files, **kwargs)
        except Exception as e:
            return {
                'success': False,
                'error': 'file_read_error',
                'message': f'读取文件失败: {str(e)}'
            }

    @staticmethod
    def download_file(url: str, save_path: str, chunk_size: int = 8192, **kwargs) -> Dict[str, Any]:
        """
        下载文件

        Args:
            url: 下载URL
            save_path: 保存路径
            chunk_size: 块大小
            **kwargs: 其他请求参数

        Returns:
            Dict: 下载结果
        """
        try:
            # 创建保存目录
            os.makedirs(os.path.dirname(save_path), exist_ok=True)

            # 流式下载
            result = HttpRequestUtils._make_request(
                'GET', url, stream=True, **kwargs)

            if not result['success']:
                return result

            response = result.get('response')
            if not response:
                return {
                    'success': False,
                    'error': 'no_response',
                    'message': '无法获取响应对象'
                }

            # 写入文件
            with open(save_path, 'wb') as f:
                for chunk in response.iter_content(chunk_size=chunk_size):
                    if chunk:
                        f.write(chunk)

            file_size = os.path.getsize(save_path)
            logger.info(f"📥 文件下载完成: {save_path} ({file_size} bytes)")

            return {
                'success': True,
                'message': '文件下载成功',
                'file_path': save_path,
                'file_size': file_size,
                'url': url
            }

        except Exception as e:
            logger.error(f"💥 文件下载失败: {url} - {str(e)}")
            return {
                'success': False,
                'error': 'download_error',
                'message': f'下载失败: {str(e)}',
                'url': url
            }

    @staticmethod
    def request_with_retry(method: str, url: str, max_retries: int = 3,
                           retry_delay: float = 1.0, **kwargs):
        """
        带重试机制的请求

        Args:
            method: HTTP方法
            url: 请求URL
            max_retries: 最大重试次数
            retry_delay: 重试延迟（秒）
            **kwargs: 其他请求参数

        Returns:
            Dict: 响应结果
        """
        import time
        result = None
        for attempt in range(max_retries + 1):
            result = HttpRequestUtils._make_request(method, url, **kwargs)

            if result['success']:
                return result

            if attempt < max_retries:
                logger.warning(
                    f"🔄 请求失败，{retry_delay}秒后重试 ({attempt + 1}/{max_retries})")
                time.sleep(retry_delay)
                retry_delay *= 2  # 指数退避
            else:
                logger.error(f"❌ 请求最终失败，已重试{max_retries}次")

        return result

    @staticmethod
    def get_json(url: str, **kwargs) -> Dict[str, Any]:
        """
        便捷方法：获取JSON数据

        Args:
            url: 请求URL
            **kwargs: 其他请求参数

        Returns:
            Dict: JSON数据或错误信息
        """
        result = HttpRequestUtils.get(url, **kwargs)
        if result['success'] and 'json' in result:
            return result['json']
        return result

    @staticmethod
    def post_json(url: str, json_data: Dict, **kwargs) -> Dict[str, Any]:
        """
        便捷方法：发送JSON数据

        Args:
            url: 请求URL
            json_data: JSON数据
            **kwargs: 其他请求参数

        Returns:
            Dict: 响应结果
        """
        return HttpRequestUtils.post(url, json_data=json_data, **kwargs)

    @staticmethod
    def set_default_headers(headers: Dict[str, str]):
        """
        设置默认请求头

        Args:
            headers: 请求头字典
        """
        HttpRequestUtils.DEFAULT_HEADERS.update(headers)

    @staticmethod
    def set_default_timeout(timeout: int):
        """
        设置默认超时时间

        Args:
            timeout: 超时时间（秒）
        """
        HttpRequestUtils.DEFAULT_TIMEOUT = timeout
